/*
 * main.c
 *
 * Created: 15/05/2012 10:34:16
 *  Author: Dani
 */

/* ----------- Communication Protocol ---------------
	Receiving Data:
	ticket name	c1	c2 c3 c4
	ticket: uint8 / name: string / weight: uint16
	
	Sending Data:
		OK: 0
		Error: 1 container_number c1 c2 c3 c4
------------------------------------------------- */

#include <avr/io.h>
#define F_CPU 8000000
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdio.h> // printf
#include "lcd162.h"
#include "weight_sensor.h"
#include "engine.h"
#include "switch.h"
#include "serving_process.h"
#include "uart.h"
#include "calibration.h"
//#include "buzzer.h"

// Length of the mix name
#define STR_NAME_LENGHT 10

void Initialization();


int main(void)
{	
	// Different to 0 if there are any errors.
	uint8_t error = 0;
	// String used for sending/receiving data
	char str[STR_MAX_LENGHT] = {'\0'};
	// Save the engine which is stuck
	uint8_t engine_stuck = 0;
	// Purchase ticket number
	uint16_t ticket = 0;
	// Name of the product
	char mix_name[STR_NAME_LENGHT];
	// Weight of each product to serve. Later, real weight served.
	uint16_t weight[NUMBER_CONTAINERS];
	// Temporal data
	int16_t weight_temp;
	uint8_t i = 0;
	
	Initialization();
	// Enters the calibration process if a button is pressed
	// before certain time.
	CalibrationEnter();
	
	while (1)
	{
		/*----------------------------------
				Product selection
		----------------------------------*/
		
		// Welcome 
		LCDClear();
		LCDDispString("----Welcome!----");
		LCDGotoXY(0,1);
		LCDDispString("Select your mix ");
		
		// Wait a OK message from the system 
		// ( 10 = '\n' )
		while (UARTReadChar() != 10) 
		{}
		// Send ready message.
		UARTSendString("ready");
		
		// Wait for orders and read them.
		UARTReadString(str);
		sscanf(str,"%u %s %u %u %u %u", &ticket, mix_name, &weight[0], &weight[1], &weight[2], &weight[3]);
		
		// Show selling information on the screen.
		sprintf(str,"%s. T:%u.", mix_name, ticket);
		LCDClear();
		LCDDispString(str);
		
		// Wait for the client to press the Start button S3
		LCDGotoXY(0,1);
		LCDDispString("Press start.");
		while (S3() == 0)
		{}
		// Delete the second line
		LCDGotoXY(0,1);
		LCDDispString("            ");

		/* ---------------------------
				Product mixing
		-------------------------------*/
		for (uint8_t container_counter = 0; ((container_counter < NUMBER_CONTAINERS)); container_counter++)
		{
			if ((weight[container_counter] != 0) & (error == 0))
			{
				weight_temp = ServeContainer((container_counter), weight[container_counter]);
				
				// Update the weight served
				weight[container_counter] = weight_temp;
							
				// Check errors.
				error = ErrorSell();
				// If there is stuck, save the container/engine number.
				if (error == (1<<STUCK))
				{
					engine_stuck = EngineOn();	
				}
			}
			// If there is an error or the weight to serve is 0, the weight served will be 0.
			else
			{
				weight[container_counter] = 0;
			}				
		}
		
		/*----------------------------------
				Product serving
		----------------------------------*/
		if (error == 0)
		{
			error = ServeMix();
			
			// Last container stuck?
			if (error == (1<<STUCK))
			{
				engine_stuck = CONTAINER_MIX;
			}
		}
		
		/*------------------------------------------
			Sending serving data and restarting
		-------------------------------------------*/
				
		// If there are no errors.
		if (error == 0)
		{
			// Send weights served back to the system
			sprintf(str,"0 0 %u %u %u %u", weight[0], weight[1], weight[2], weight[3]);
			UARTSendString(str);
			
			// Show information to the client.
			LCDClear();
			LCDDispString("Please take your");
			LCDGotoXY(0,1);
			LCDDispString("bag and enjoy!");
			// Wait for the client to take his product
			_delay_ms(3000);
		}
		else
		{	 
			// Error. Return the served weights, if a motor is stuck, its number.
			sprintf(str,"1 %u %u %u %u %u", (engine_stuck), weight[0], weight[1], weight[2], weight[3]);
			UARTSendString(str);
			// Show information to the client.
			LCDClear();
			LCDDispString("Error. Contact");
			LCDGotoXY(0,1);
			LCDDispString("the responsible.");		
		}
		
		// ------ Delete previous data ------
		for (i = 0; i < STR_MAX_LENGHT; i++)
		{
			str[i] = 0;
		}
		for (i = 0; i < STR_NAME_LENGHT; i++)
		{
			mix_name[i] = 0;
		}
		ticket = 0;
		
		/*---------------------------------
			Error -> wait for restart
		-----------------------------------*/
		while (error)
		{}		
	}
	return 0;	
}

void Initialization()
{	
	sei();	
	LCDInit();
	LCDDispString("Starting...");
	//BuzzerInit();	
	EngineInit();
	SwitchInit();
	Timer1Init();
	WeightSensorInit();
	UARTInit(9600,8);
	
	LCDClear();
}

// Switch 2 interrupt. Used for lab purposes.
ISR(S2)
{
	EngineControl(4, SPEED_MAX);
}